package com.umakr.ax.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import sun.misc.BASE64Encoder;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * 身份证验证辅助类
 *
 * @author umakr
 */
public final class IDCardUtil {
	private IDCardUtil() {
	}
	protected static final Log logger = LogFactory.getLog(IDCardUtil.class);
	/**11个校验码字符*/
	static final char[] CODE = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
	/**18个加权因子*/
	static final int[] FACTOR = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };

	/**
	 * 修补15位居民身份证号码为18位，并校验15位身份证有效性
	 * 
	 * @param personIDCode 十五位身份证号码
	 * @return String 十八位身份证号码
	 * @throws 无效的身份证号
	 */
	public static final String fixPersonIDCodeWithCheck(String personIDCode) throws Throwable {
		if (personIDCode == null || personIDCode.trim().length() != 15){
			throw new RuntimeException("输入的身份证号不足15位，请检查");
		}

		if (!isIdentity(personIDCode)) {
			throw new RuntimeException("输入的身份证号无效，请检查");
		}

		return fixPersonIDCodeWithoutCheck(personIDCode);
	}

	/**
	 * 修补15位居民身份证号码为18位，不校验身份证有效性
	 * 
	 * @param personIDCode 十五位身份证号码
	 * @return 十八位身份证号码
	 * @throws 身份证号参数不是15位
	 */
	public static final String fixPersonIDCodeWithoutCheck(String personIDCode) {
		if (personIDCode == null || personIDCode.trim().length() != 15) {
			throw new RuntimeException("输入的身份证号不足15位，请检查");
		}

		// 15位身份证补'19'
		String id17 = personIDCode.substring(0, 6) + "19" + personIDCode.substring(6, 15);

		int[] idcd = new int[18];
		// 根据公式 ∑(ai×Wi) 计算
		int sum;
		// 第18位校验码
		int remainder;
		for (int i = 0; i < 17; i++) {
			idcd[i] = Integer.parseInt(id17.substring(i, i + 1));
		}
		sum = 0;
		for (int i = 0; i < 17; i++) {
			sum = sum + idcd[i] * FACTOR[i];
		}
		remainder = sum % 11;
		String lastCheckBit = String.valueOf(CODE[remainder]);
		return id17 + lastCheckBit;
	}

	/**
	 * 从身份证号中获取出生日期，身份证号可以为15位或18位
	 * 
	 * @param identity 身份证号
	 * @return 出生日期
	 * @throws 身份证号出生日期段有误
	 */
	public static final Timestamp getBirthdayFromPersonIDCode(String identity) throws Throwable {
		String id = getFixedPersonIDCode(identity);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		try {
			Timestamp birthday = new Timestamp(sdf.parse(id.substring(6, 14)).getTime());
			return birthday;
		} catch (ParseException e) {
			throw new RuntimeException("不是有效的身份证号，请检查");
		}
	}

	/**
	 * 将传入的身份证号码进行校验，并返回一个对应的18位身份证
	 * 
	 * @param personIDCode 身份证号码
	 * @return String 十八位身份证号码
	 * @throws 无效的身份证号
	 */
	public static final String getFixedPersonIDCode(String personIDCode) throws Throwable {
		if (personIDCode == null) {
			throw new RuntimeException("输入的身份证号无效，请检查");
		}

		if (personIDCode.length() == 18) {
			if (isIdentity(personIDCode)) {
				return personIDCode;
			}else {
				throw new RuntimeException("输入的身份证号无效，请检查");
			}
		} else if (personIDCode.length() == 15) {
			return fixPersonIDCodeWithCheck(personIDCode);
		}else {
			throw new RuntimeException("输入的身份证号无效，请检查");
		}
	}

	/**
	 * 从身份证号获取性别
	 * 
	 * @param identity 身份证号
	 * @return 性别代码
	 * @throws Exception 无效的身份证号码
	 */
	public static final Sex getGenderFromPersonIDCode(String identity) throws Throwable {
		String id = getFixedPersonIDCode(identity);
		char sex = id.charAt(16);
		return sex % 2 == 0 ? Sex.Female : Sex.Male;
	}

	/**
	 * 判断是否是有效的18位或15位居民身份证号码
	 * 
	 * @param identity 18位或15位居民身份证号码
	 * @return 是否为有效的身份证号码
	 */
	public static final boolean isIdentity(String identity) {
		if (identity == null) {
			return false;
		}
		if (identity.length() == 18 || identity.length() == 15) {
			String id15 = null;
			if (identity.length() == 18) {
				id15 = identity.substring(0, 6) + identity.substring(8, 17);
			}else {
				id15 = identity;
			}
			try {
				// 校验是否为数字字符串
				Long.parseLong(id15);

				String birthday = "19" + id15.substring(6, 12);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
				// 校验出生日期
				sdf.parse(birthday);
				if (identity.length() == 18 && !fixPersonIDCodeWithoutCheck(id15).equals(identity)) {
					// 校验18位身份证
						return false;
				}
			} catch (Exception e) {
				return false;
			}
			return true;
		} else {
			return false;
		}
	}

	public static void main(String[] args) throws Throwable {
		aliIDCardDistinguish("http://test22umake.oss-cn-beijing.aliyuncs.com/test/Help/Cards201801/161_201801130357_4167/image-7acb7abb-b74b-49d2-a003-06d369e43611.jpg");

	}

	/**
	 * 性别
	 * 
	 * @author ShenHuaJie
	 */
	public enum Sex {
		/**
		 * 未知
		 */
		Other("未知", 0),
		/**
		 * 男
		 */
		Male("男", 1),
		/**
		 * 女
		 */
		Female("女", 2);

		private String name;
		private Integer value;

		private Sex(String name, Integer value) {
			this.name = name;
			this.value = value;
		}

		public Integer getValue() {
			return value;
		}

		@Override
        public String toString() {
			return this.name;
		}
	}


	public static Object aliIDCardDistinguish(String fileUrl) {
		try {
			FileInputStream fileInputStream = new FileInputStream(new File(fileUrl));
			byte[] buffer = readInputStream(fileInputStream);
			String encodeStr = new BASE64Encoder().encode(buffer);
			String host = "https://dm-51.data.aliyun.com";
			String path = "/rest/160601/ocr/ocr_idcard.json";
			String method = "POST";
			String appcode = "9d3a6390bcc445fdbc840bd0b67ac356";
			Map<String, String> headers = new HashMap<>(16);
			//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
			headers.put("Authorization", "APPCODE " + appcode);
			//根据API的要求，定义相对应的Content-Type
			headers.put("Content-Type", "application/json; charset=UTF-8");
			Map<String, String> querys = new HashMap<>(16);
			String bodys = "{\"inputs\":[{\"image\":{\"dataType\":50,\"dataValue\":\""+encodeStr+"\"},\"configure\":{\"dataType\":50,\"dataValue\":\"{\\\"side\\\":\\\"face\\\"}\"}}]}";

			HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
			logger.info(response.toString());
			//获取response的body
			JSONObject jo = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
			JSONArray outputs = (JSONArray)jo.get("outputs");
			Map<String,Object> outputValue = (Map<String,Object>)((JSONObject)outputs.get(0)).get("outputValue");
			return JSONObject.parseObject(outputValue.get("dataValue").toString());
		} catch (Exception e) {
			return "error";
		}
	}

	private static byte[] readInputStream(InputStream inStream) throws Exception{
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while( (len=inStream.read(buffer)) != -1 ){
			outStream.write(buffer, 0, len);
		}
		inStream.close();
		return outStream.toByteArray();
	}


}
